package notYet;

import java.util.List;

import processing.core.PApplet;
import processing.core.PVector;
import toxi.geom.Rect;
import toxi.physics2d.VerletParticle2D;
import toxi.physics2d.VerletPhysics2D;
import toxi.physics2d.VerletSpring2D;
import utils.Utils;

public class CopyOfMC_SoftBodySquare {

	/**
	 * <p>
	 * Softbody square demo is showing how to create a 2D square mesh out of
	 * verlet particles and make it stable enough to avoid total structural
	 * deformation by including an inner skeleton.
	 * </p>
	 * 
	 * <p>
	 * Usage: move mouse to drag/deform the square
	 * </p>
	 */

	/*
	 * Copyright (c) 2008-2009 Karsten Schmidt
	 * 
	 * This demo & library is free software; you can redistribute it and/or
	 * modify it under the terms of the GNU Lesser General Public License as
	 * published by the Free Software Foundation; either version 2.1 of the
	 * License, or (at your option) any later version.
	 * 
	 * http://creativecommons.org/licenses/LGPL/2.1/
	 * 
	 * This library is distributed in the hope that it will be useful, but
	 * WITHOUT ANY WARRANTY; without even the implied warranty of
	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
	 * General Public License for more details.
	 * 
	 * You should have received a copy of the GNU Lesser General Public License
	 * along with this library; if not, write to the Free Software Foundation,
	 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
	 */

	PApplet main;
	
	int DIM = 25;
	int REST_LENGTH = 10;
	float STRENGTH = 0.125f;
	//float STRENGTH = 0.0000001f;
	//float INNER_STRENGTH = 0.5f;
	float INNER_STRENGTH = 1f;
	
	VerletPhysics2D physics;
	VerletParticle2D head;
	VerletParticle2D tail;
	VerletSpring2D verletTest1;
	VerletSpring2D verletTest2;
	
	public CopyOfMC_SoftBodySquare(PApplet main, List<PVector> points){
		this.main = main;
		this.initialize(points);
	}

	public void initialize(List<PVector> points) {
		physics = new VerletPhysics2D();
		//physics.setGravity(new Vec2D(0, 0.3f));
		physics.setWorldBounds(new Rect(0, 0, main.width, main.height));
		
		if(points != null){
			head = populateWithPoints(points);
			for (int i = 0; i < physics.springs.size(); i++) {
				//if(i%8 == 0){
					VerletSpring2D verletSpring2D = physics.springs.get(i);
					verletSpring2D.setStrength(main.random(INNER_STRENGTH - 0.5f));
					verletSpring2D.setRestLength(PVector.dist(new PVector(verletSpring2D.a.x, verletSpring2D.a.y), new PVector(verletSpring2D.b.x, verletSpring2D.b.y)));
				//}
			}
			//head = physics.particles.get(physics.particles.size() - 1);
		} else {
			populateWithParticlesAndSprings();
			createSkeleton();
			head = physics.particles.get((DIM - 1) / 2);
		}
		
		head.lock();
	}

	private void createSkeleton() {
		float len = PApplet.sqrt(PApplet.sq(REST_LENGTH * (DIM - 1)) * 2);
		createSkeleton(0, physics.particles.size() - 1, len);
		createSkeleton(DIM - 1, physics.particles.size() - DIM, len);
	}
	
	private void createSkeleton(int index1, int index2, float length) {
		VerletParticle2D p = physics.particles.get(index1);
		VerletParticle2D q = physics.particles.get(index2);
		VerletSpring2D s = new VerletSpring2D(p, q, length, INNER_STRENGTH);
		physics.addSpring(s);
	}

	private void populateWithParticlesAndSprings() {
		int idx = 0;
		for (int y = 0; y < DIM; y++) {
			for (int x = 0; x < DIM; x++) {
				VerletParticle2D p = new VerletParticle2D(x * REST_LENGTH, y * REST_LENGTH);
				physics.addParticle(p);
				if (x > 0) {
					VerletSpring2D s = new VerletSpring2D(p, physics.particles.get(idx - 1), main.random(REST_LENGTH), STRENGTH);
					physics.addSpring(s);
				}
				if (y > 0) {
					VerletSpring2D s = new VerletSpring2D(p, physics.particles.get(idx - DIM), main.random(REST_LENGTH), STRENGTH);
					physics.addSpring(s);
				}
				idx++;
			}
		}
	}
	
	private VerletParticle2D populateWithPoints(List<PVector> points){
		PVector centralPoint = Utils.getCentralPoint(points);
		VerletParticle2D centralParticle = new VerletParticle2D(centralPoint.x, centralPoint.y);
		physics.addParticle(centralParticle);
		VerletSpring2D spring = null;
		VerletParticle2D lastParticle = null;
		VerletParticle2D firstParticle = null;
		for (int i = 0; i < points.size(); i++) {
			PVector p = points.get(i);
			VerletParticle2D particle = new VerletParticle2D(p.x, p.y);
			physics.addParticle(particle);
			
			spring = new VerletSpring2D(centralParticle, particle, main.random(REST_LENGTH), STRENGTH);
			physics.addSpring(spring);
			
			if(i == 0){
				firstParticle = particle;
			}
			if(i == (points.size() - 1)){
//				spring = new VerletSpring2D(particle, firstParticle, main.random(REST_LENGTH), STRENGTH);
//				physics.addSpring(spring);
				lastParticle = firstParticle;
			} 
			
			if(lastParticle != null){
				spring = new VerletSpring2D(lastParticle, particle, main.random(REST_LENGTH), STRENGTH);
				physics.addSpring(spring);
			}
			
			lastParticle = particle;
		}
		return centralParticle;
	}

	public void drawMalha(float x, float y, float rotation) {
		main.stroke(255);
		head.set(x, y);
		//head.rotate(rotation);
		physics.update();
		
		for (VerletSpring2D spring : physics.springs) {
			main.line(spring.a.x, spring.a.y, spring.b.x, spring.b.y);
		}
		
		for(VerletParticle2D particle : physics.particles){
			main.ellipse(particle.x, particle.y, 3, 3);
		}
	}

//	@Override
//	public void keyPressed() {
//		//System.out.println("key:"+key);
//		if(key == ' '){
//			INNER_STRENGTH = INNER_STRENGTH + 0.01f;
//		} else if (key == 'n'){
//			INNER_STRENGTH = INNER_STRENGTH - 0.01f;
//		} else if (key == 'p'){
//			createSkeleton((int)random(DIM-1), (int)random(DIM-1), (int)random(width));
//		}
//		verletTest1.setStrength(INNER_STRENGTH);
//		verletTest2.setStrength(INNER_STRENGTH);
//		physics.update();
//	}

//	static public void main(String args[]) {
//		PApplet.main(new String[] { "--bgcolor=#FFFFFF", "notYet.CopyOfMC_SoftBodySquare" });
//	}
}
